package com.gateio.flutter.lib_furnace.container

import android.content.Context
import android.util.Log
import com.gateio.flutter.lib_furnace.GTFlutter
import com.gateio.flutter.lib_furnace.GTFlutterInitializer
import com.gateio.flutter.lib_furnace.protocol.IGTFlutterHostDelegate
import com.gateio.flutter.lib_furnace.util.GTFurnaceConstant
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import io.flutter.embedding.android.FlutterFragment
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache

/**
 * Author: Shper
 * Created: 2023/6/12
 */
typealias FragmentConfigureFlutterEngine = (flutterEngine: FlutterEngine) -> Unit

open class GTFlutterFragment: FlutterFragment() {

    companion object {
        fun withCachedEngineId(cachedEngineId: String) = GTCachedEngineFragmentBuilder(GTFlutterFragment::class.java, cachedEngineId)
    }

    private var hostDelegate: IGTFlutterHostDelegate? = null

    private var configureFlutterEngineFun: FragmentConfigureFlutterEngine? = null
    var routerName: String = ""

    override fun onAttach(context: Context) {
        Log.d("GTFlutter", "$this -  onAttach")
        // 判断 FlutterEngineCache 不包含需要的 FlutterEngine时，重新创建 Flutter 引擎
        val transparentStatusBar = arguments?.getBoolean(GTFurnaceConstant.KEY_TRANSPARENT_STATUS_BAR, true) ?: true
        val customEngineId = arguments?.getString(GTFurnaceConstant.KEY_CUSTOM_ENGINE_ID, null) ?: ""
        routerName = arguments?.getString(GTFurnaceConstant.KEY_ROUTER_NAME, null) ?: ""
        val engineId: String = customEngineId.ifBlank { cachedEngineId ?: routerName }

        if (!FlutterEngineCache.getInstance().contains(engineId)) {
            Log.w("GTFlutter", "$this -  flutterEngineCache is not contains $engineId")
            val routeParams = arguments?.getString(GTFurnaceConstant.KEY_ROUTER_PARAMS, null) ?: "{}"
            val routeParamMap: HashMap<String, Any> = Gson().fromJson(routeParams, object : TypeToken<HashMap<String, Any>>() {}.type)
            GTFlutter.createAndRunEngine(context, routerName, routeParamMap, engineId, transparentStatusBar)
        }

        hostDelegate = GTFlutterInitializer.getHostDelegate()
        super.onAttach(context)
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        Log.d("GTFlutter", "$this - configureFlutterEngine")
        super.configureFlutterEngine(flutterEngine)
        hostDelegate?.configureFlutterEngine(context, false, flutterEngine)
        // Fragment 特有的 configureFlutterEngine
        configureFlutterEngineFun?.invoke(flutterEngine)
    }

    override fun onDestroy() {
        Log.d("GTFlutter", "$this - onDestroy")
        super.onDestroy()
        GTFlutter.pageStartedList.remove(routerName)
    }

    /**
     * 获取 Flutter 引擎Id
     */
    fun getEngineId(): String? {
        return cachedEngineId
    }


    class GTCachedEngineFragmentBuilder(subclass: Class<out GTFlutterFragment>,
                                        cachedEngineId: String) : CachedEngineFragmentBuilder(subclass, cachedEngineId) {

        private var routerName: String? = null
        private var routeParams: String? = null
        private var customEngineId: String = ""
        private var sharedEngine: Boolean = false
        private var transparentStatusBar: Boolean = true

        private var configureFlutterEngineFun: FragmentConfigureFlutterEngine? = null

        fun onConfigureFlutterEngine(configureFlutterEngine: FragmentConfigureFlutterEngine?): GTCachedEngineFragmentBuilder {
            this.configureFlutterEngineFun = configureFlutterEngine
            return this
        }

        fun routerName(routerName: String): GTCachedEngineFragmentBuilder {
            this.routerName = routerName
            return this
        }

        fun routeParams(routeParams:Map<String, Any>?): GTCachedEngineFragmentBuilder {
            routeParams?.let {
                this.routeParams = Gson().toJson(it)
            }
            return this
        }

        fun customEngineId(customEngineId: String): GTCachedEngineFragmentBuilder {
            this.customEngineId = customEngineId
            return this
        }

        fun sharedEngine(sharedEngine: Boolean): GTCachedEngineFragmentBuilder {
            this.sharedEngine = sharedEngine
            return this
        }

        fun transparentStatusBar(transparentStatusBar: Boolean): GTCachedEngineFragmentBuilder {
            this.transparentStatusBar = transparentStatusBar
            return this
        }

        override fun <T : FlutterFragment> build(): T {
            val fragment = super.build<T>()
            fragment.arguments?.putString(GTFurnaceConstant.KEY_ROUTER_NAME, routerName)
            fragment.arguments?.putString(GTFurnaceConstant.KEY_ROUTER_PARAMS, routeParams)
            fragment.arguments?.putString(GTFurnaceConstant.KEY_CUSTOM_ENGINE_ID, customEngineId)
            fragment.arguments?.putBoolean(GTFurnaceConstant.KEY_TRANSPARENT_STATUS_BAR, transparentStatusBar)

            if (fragment is GTFlutterFragment) {
                fragment.configureFlutterEngineFun = configureFlutterEngineFun
            }

            return fragment
        }
    }

}